package edu.chl.grupp11.aegas.controller.imp;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import edu.chl.grupp11.aegas.constants.FileTypesConst;
import edu.chl.grupp11.aegas.controller.ErrorControllerFactory;
import edu.chl.grupp11.aegas.controller.FileControllerFactory;
import edu.chl.grupp11.aegas.controller.IBrowserController;
import edu.chl.grupp11.aegas.controller.IErrorController;
import edu.chl.grupp11.aegas.controller.IFileController;
import edu.chl.grupp11.aegas.model.AbstractConfig;
import edu.chl.grupp11.aegas.model.ConfigFactory;

public class BrowserController implements IBrowserController {
	private JFileChooser fileChooser = new JFileChooser();
	private FileNameExtensionFilter allFilesFilter = FileTypesConst.ALL_FILE_FILTER;
	private FileNameExtensionFilter imageFilter = FileTypesConst.IMAGE_FILE_FILTER;
	private FileNameExtensionFilter audioFilter = FileTypesConst.AUDIO_FILE_FILTER;
	private AbstractConfig config = ConfigFactory.getSharedConfig();
	private IErrorController errorController = ErrorControllerFactory
			.getErrorController();
	private IFileController fileController = FileControllerFactory
			.getFileController();

	public BrowserController() {
		fileChooser.addChoosableFileFilter(audioFilter);
		fileChooser.addChoosableFileFilter(imageFilter);
		fileChooser.addChoosableFileFilter(allFilesFilter);
		fileChooser.setAcceptAllFileFilterUsed(false);
		fileChooser.setMultiSelectionEnabled(true);
	}

	private void addFileToModel(File f) {
		if (allFilesFilter.accept(f)) {
			if (!fileController.hasFile(f)) {
				fileController.addFile(f);
			} else {
				errorController.setErrorMessage(null, config
						.getResourceBundle().getString("error5"));
			}
		} else if (!allFilesFilter.accept(fileChooser.getSelectedFile())) {
			errorController.setErrorMessage(null, config.getResourceBundle()
					.getString("error6"));
		}
	}

	private ArrayList<File> getAllFilesInSubFolders(File folder) {
		ArrayList<File> acceptedFiles = new ArrayList<File>();

		acceptedFiles.addAll(getFilesInFolder(folder));

		for (File subFolder : getSubFolders(folder)) {
			if (getSubFolders(subFolder) != null) {
				acceptedFiles.addAll(getAllFilesInSubFolders(subFolder));
			}
		}

		return acceptedFiles;
	}

	private ArrayList<File> getFilesInFolder(File folder) {
		ArrayList<File> acceptedFiles = new ArrayList<File>();
		for (File f : folder.listFiles()) {
			if (f.isFile() && allFilesFilter.accept(f)) {
				acceptedFiles.add(f);
			}
		}
		return acceptedFiles;
	}

	private ArrayList<File> getSubFolders(File folder) {
		if (config.isSearchSubFolders()) {
			File[] filesInSubFolder = folder.listFiles();
			ArrayList<File> allFoldersInSubFolder = new ArrayList<File>();
			for (File f : filesInSubFolder) {
				if (f.isDirectory()) {
					allFoldersInSubFolder.add(f);
				}
			}
			return allFoldersInSubFolder;
		} else {
			return null;
		}
	}

	@Override
	public void openFileBrowser() {
		fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
		int rVal = fileChooser.showOpenDialog(null);
		if (rVal == JFileChooser.APPROVE_OPTION) {
			for (File f : fileChooser.getSelectedFiles()) {
				if (f.canRead()) {
					addFileToModel(f);
				} else {
					errorController.setErrorMessage(
							null,
							config.getResourceBundle().getString("error7")
									+ f.getName());
				}

			}
		} else if (rVal == JFileChooser.CANCEL_OPTION) {
		}
	}

	@Override
	public void openFolderBrowser() {
		ArrayList<File> selectedFolders = new ArrayList<File>();

		fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int rVal = fileChooser.showOpenDialog(null);
		if (rVal == JFileChooser.APPROVE_OPTION) {
			selectedFolders
					.addAll(Arrays.asList(fileChooser.getSelectedFiles()));
		} else if (rVal == JFileChooser.CANCEL_OPTION) {
		}

		for (File folder : selectedFolders) {
			if (config.isSearchSubFolders()) {
				for (File file : getAllFilesInSubFolders(folder)) {
					addFileToModel(file);
				}
			} else {
				for (File file : getFilesInFolder(folder)) {
					addFileToModel(file);
				}
			}
		}
	}

	@Override
	public void openURLBrowser() throws IOException {
		String url = JOptionPane.showInputDialog("Enter the URL of the file");

		if (url != null) {
			java.io.BufferedInputStream in = new java.io.BufferedInputStream(
					new java.net.URL(url).openStream());

			String filename = "downloads/"
					+ new URL(url).getFile().substring(
							new URL(url).getFile().lastIndexOf('/') + 1);
			java.io.FileOutputStream fos = new java.io.FileOutputStream(
					filename);

			java.io.BufferedOutputStream bout = new BufferedOutputStream(fos,
					1024);

			byte[] data = new byte[1024];
			int x = 0;

			while ((x = in.read(data, 0, 1024)) >= 0) {
				bout.write(data, 0, x);
			}

			bout.close();
			in.close();
			addFileToModel(new File(filename));
		}
	}
}